38장. 실전 ② 사내 RAG 챗봇
이 장의 목표 회사 위키·매뉴얼·정책 문서를 학습한 사내 챗봇 을 처음부터 끝까지 만듭니다.
26·27장의 개념이 실제 동작하는 도구로 합쳐집니다.
38.1 큰 그림
[사내 문서: 위키 / PDF / Notion / Confluence / 로컬 폴더]
│
▼
[ 인덱싱 파이프라인 ]
- 문서 추출
- 청킹
- 임베딩
- 벡터 DB 저장
│
▼
[ 벡터 DB (Qdrant) ]
│
▼
[ Open WebUI ← Ollama (Qwen3-32B + bge-m3) ]
│
▼
[ 사용자 ]
3개 컨테이너 / 서비스가 떠 있는 구조.
38.2 도구 결정
이번 장의 표준 스택:
| 역할 | 도구 |
|---|---|
| LLM | Ollama + qwen3:32b |
| 임베딩 | Ollama + bge-m3 |
| 벡터 DB | Qdrant |
| 청킹·검색·UI | Open WebUI |
| 대안 | LangChain + Streamlit |
장점:
- 사내망에 통째로 배포 가능
- 다중 사용자 자연스러움
- GitHub·Slack·Notion MCP 연결 쉬움 (30장)
38.3 1단계 — Ollama 모델 준비
$ ollama pull qwen3:32b
$ ollama pull bge-m3
$ ollama serve
(ollama serve 는 GUI 앱이 떠 있으면 자동.)
38.4 2단계 — Qdrant 띄우기
$ mkdir -p ~/Developer/rag-chatbot/qdrant_storage
$ docker run -d \
--name qdrant \
-p 6333:6333 -p 6334:6334 \
-v ~/Developer/rag-chatbot/qdrant_storage:/qdrant/storage \
qdrant/qdrant
확인:
$ curl http://localhost:6333/healthz
38.5 3단계 — Open WebUI 띄우기
$ docker run -d -p 3000:8080 \
-e OPENAI_API_BASE_URL=http://host.docker.internal:11434/v1 \
-e OPENAI_API_KEY=ollama \
-v open-webui:/app/backend/data \
--name open-webui \
--restart always \
ghcr.io/open-webui/open-webui:main
http://localhost:3000 접속 → 회원가입 (첫 가입자가 관리자).
설정 → Models 에서 qwen3:32b 가 보이면 성공.
38.6 4단계 — Open WebUI에 RAG 켜기
Open WebUI는 RAG가 내장 되어 있습니다.
설정 → Documents :
- Embedding Model:
bge-m3(Ollama 사용) - Chunk Size: 500
- Chunk Overlap: 100
- Top K: 4
설정 → Vector DB (선택):
- 기본은 Chroma (간단)
- Qdrant 사용:
QDRANT_URI=http://host.docker.internal:6333
38.7 5단계 — 문서 업로드
Open WebUI의 Documents 페이지:
- 드래그 드롭으로 PDF/Markdown/Word 업로드
- 자동으로 청킹 + 임베딩 + 벡터 DB 저장
URL 인덱싱도 됩니다.
38.8 6단계 — 첫 질문
채팅 화면에서 입력창 좌측 + → #문서 선택.
#휴가규정
정직원 연차는 며칠인가요?
답에 인용 (citation) 표시가 함께 나옵니다.
38.9 시스템 프롬프트 표준 (사내 챗봇 버전)
설정 → Default Models → System Prompt :
당신은 비트북 회사의 사내 비서입니다.
규칙:
1. 답변은 한국어 존댓말로.
2. 첨부된 사내 문서를 근거로만 답하세요.
3. 문서에 없는 내용은 "사내 자료에서 확인되지 않습니다"라고 답하세요.
4. 답변 끝에 참고한 문서 번호([1], [2])를 표기하세요.
5. 사람·계정·연봉 등 개인정보는 답하지 마세요.
이 한 줄이 환각·거절(34장) 안정성의 80%.
38.10 RAG 품질 점검 체크
업로드 후 첫 테스트 셋 (30개 정도):
| 질문 | 기대 답 | 실제 답 | 평가 |
|---|---|---|---|
| 정직원 연차? | 15일 | 15일 | ✅ |
| 휴가 신청 절차? | 그룹웨어 | 그룹웨어 | ✅ |
| 사장님 이메일? | 거절 | 거절 | ✅ |
| … | … | … | … |
40장에서 자세한 평가 루틴.
38.11 자주 만나는 RAG 함정 (실전)
한국어 문서가 잘 검색 안 됨
- 임베딩 모델을
bge-m3로 (다국어 강함) - 청크 사이즈 300~500 자
- 한국어 폰트 PDF는 텍스트 추출 품질이 낮을 수 있음 → OCR 전처리 (31장)
표·코드 청킹이 깨짐
- 마크다운으로 변환 후 인덱싱
- 표는 별도 행 단위 청크
같은 문서가 여러 번 인용됨
- 중복 청크 제거
- Top K를 4 → 6 로 늘려서 다양성 확보
시스템 프롬프트가 무시됨
- 작은 모델(8B 이하) 일 때 자주 발생
- 14B 이상 권장
- 시스템 프롬프트를 영어로 작성하면 잘 따르는 모델도 있음
38.12 Reranker 적용 — 품질 한 단계 위 (선택)
Open WebUI는 Hybrid Search + Reranker 지원 (버전에 따라).
설정에서:
- Reranker Model:
bge-reranker-v2-m3 - Hybrid Search: ON
체감 정확도가 크게 올라갑니다.
38.13 사내망 배포
지금은 다 localhost. 사내망에 두려면:
Ollama가 외부에서도 접근 가능하게
$ launchctl setenv OLLAMA_HOST "0.0.0.0:11434"
Open WebUI는 사내 IP / 도메인
docker run 의 -p 호스트 부분을 0.0.0.0 으로 두고
사내 DNS에 등록 (예: chatbot.internal.bitbook.local).
인증
Open WebUI는 자체 가입·로그인 기능 내장. Single Sign-On(OIDC/OAuth)도 지원.
HTTPS
Nginx + Let’s Encrypt 또는 사내 인증서.
백업
- Qdrant 스토리지 폴더
- Open WebUI
open-webuiDocker volume
38.14 운영 — 평소 점검
| 빈도 | 점검 |
|---|---|
| 매일 | 모델·DB 컨테이너 살아있는지 |
| 주 1회 | 새 문서 인덱싱 |
| 주 1회 | 테스트 셋 30개 회귀 |
| 월 1회 | 사용 로그 검토 (안전성) |
| 분기 | 모델·임베딩 업그레이드 검토 |
38.15 한 단계 확장 — MCP 연결
30장의 MCP 서버를 Open WebUI 또는 다른 클라이언트로 연결하면 RAG + 도구 사용 챗봇이 됩니다.
"이번주 휴가 신청서 좀 만들어줘"
↓
1. RAG로 휴가 신청 규정 조회
2. notion MCP 로 양식 페이지 생성
3. slack MCP 로 부서장 알림
이 장에서 기억할 한 가지
사내 RAG 챗봇 표준 스택:
Ollama + bge-m3 + Qdrant + Open WebUI.
가장 큰 품질 차이는 모델이 아니라:
- 청킹·임베딩·Reranker
- 시스템 프롬프트
- 한국어 문서의 OCR 품질
한 번 구축하면 회사의 정보 접근성이 영구히 바뀝니다.
손으로 해볼 것
1. 38.3 ~ 38.6 절 셋업
1시간 안에 다 띄울 수 있습니다.
2. 사내 문서 5개 업로드 후 테스트 셋 10개
- 위키 5페이지, PDF 정책 1개, 회의록 1개
- 질문 10개와 기대 답 미리 적어두기
- RAG 답이 기대와 일치하는 비율 측정
70% 이상이면 사내 시범 가능.
다음 장에서는 실전 ③ 회의록 요약 파이프라인 을 만듭니다.
음성 → 받아쓰기 → 요약 → 액션 추출까지 자동화합니다.